package auth

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	nhttp "net/http"
	"time"
	"wzgames/internal/api/bindo"
	"wzgames/internal/client"
	"wzgames/internal/gloader"
	"wzgames/internal/gvalidator"
	"wzgames/internal/model/login"
	"wzgames/internal/response"
	"wzgames/pkg/logger"
	"wzgames/pkg/server/http"
	"wzgames/pkg/server/http/types"
)

func RegisterRoute(pGroup *gin.RouterGroup) {
	bizGroup := pGroup.Group("auth")
	http.MethodMapper(bizGroup, types.POST)(userAuth())
}

var userAuth = func() (string, func(c *gin.Context)) {
	uri := fmt.Sprintf("/access_token")
	return uri, func(c *gin.Context) {
		//logger.Debug("request == ", zap.String("uri", c.Request.RequestURI), zap.String("host", c.Request.Host))

		resp := types.Response{}
		var params bindo.AuthBind
		if err := c.ShouldBind(&params); err != nil {
			resp.Code = response.ErrBadRequest
			c.JSON(nhttp.StatusOK, resp)
			return
		}
		if len(params.AgtCode) > 15 || !gvalidator.IsAlphaNumeric(params.AgtCode) {
			resp.Code = response.ErrBadRequest
			resp.Message = "operator"
		} else if len(params.AgtUser) > 0 && (!gvalidator.IsAgentUname(params.AgtUser) || len(params.AgtUser) > 64) {
			resp.Code = response.ErrUsername
		} else if !gvalidator.IsAlphaNumeric(params.HashVal) || len(params.HashVal) > 64 {
			resp.Code = response.ErrSign
		} else if !gvalidator.IsNumeric(params.Stamp) || !gvalidator.CheckTimestamp(params.Stamp) {
			resp.Code = response.ErrBadRequest
			resp.Message = "stamp"
		}
		if resp.Code == 0 {
			if !gvalidator.IsAgentUid(params.AgtUid) || len(params.AgtUid) > 64 {
				resp.Code = response.ErrBadRequest
				resp.Message = "uid"
			} else if len(params.Token) > 0 && (!gvalidator.IsAgentUid(params.Token) || len(params.Token) > 250) {
				resp.Code = response.ErrBadRequest
				resp.Message = "token"
			}
		}
		if resp.Code != 0 {
			c.JSON(nhttp.StatusOK, resp)
			return
		}

		agtId, err := gvalidator.DecodeAgentID(params.AgtCode)
		if err != nil {
			logger.Error("[API] auth access token fail on decode agent code", zap.String("AgtCode", params.AgtCode))
			resp.Code = response.ErrBadRequest
			c.JSON(nhttp.StatusOK, resp)
			return
		}

		req := &login.UserAuth{
			AgtID:       agtId,
			AgtCode:     params.AgtCode,
			AgtUsername: params.AgtUser,
			AgtUserId:   params.AgtUid,
			BToken:      params.Token,
			Stamp:       params.Stamp,
			Sign:        params.HashVal,
			ClientIP:    c.ClientIP(),
			NodeId:      gloader.BootConfig().Node().NodeId,
		}

		reply := &login.UserAuthReply{}
		rpcctx, cancelFn := context.WithTimeout(context.Background(), 15*time.Second)
		err = client.GetCatClient().Call(rpcctx, "UserAuth", req, reply)
		cancelFn()
		if err != nil {
			resp.Code = response.ErrInternal
			logger.Error("[API] UserAuth fail", zap.Error(err))
		} else {
			resp.Code = int16(reply.Code)
			if reply.Code == 0 {
				resp.Code = 200
				resp.Data = reply.Token
			}
		}

		c.JSON(nhttp.StatusOK, resp)
		return
	}
}
